﻿
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;


namespace DailyFx.UI
{
	public class UISelector<T> : UIConductor<T>, IUISelector where T : class
	{
		
		/// <summary>
		///		the selected child in the collection .
		/// </summary>
		private T m_SelectedChild;


		/// <summary>
		///		c'tor
		/// </summary>
		public UISelector () : base ( false )
		{
		}

		/// <summary>
		///		The currently selected child .
		/// </summary>
		public T SelectedChild
		{
			get { return this.m_SelectedChild; }
			set { this.EnableChild(value); }
		}
		/// <summary>
		/// 
		/// </summary>
		object IUISelector.SelectedChild 
		{
			get { return this.SelectedChild; }
			set { this.SelectedChild = (T)value; }
		}


		/// <summary>
		///		Enables the specified item.
		/// </summary>
		public override void EnableChild ( T child )
		{
			if (child != null && child.Equals(SelectedChild))
			{
				if ( this.IsEnabled )
				{
					UIControlExtension.TryEnableChild( child);
					this.OnChildRequireEnabled ( child, true );
				}

				return;
			}

			this.ChangeSelectedChild ( child, false );
		}

		/// <summary>
		///		Disables the specified item.
		/// </summary>
		public override void DisableChild ( T child, bool close )
		{
			base.DisableChild( child, close ) ;
		}


		/// <summary>
		///		Changes the selected child.
		/// </summary>
		protected virtual void ChangeSelectedChild ( T current, bool closePrevious )
		{
			// disable the previous selection .
			UIControlExtension.TryDisableChild ( this.m_SelectedChild, closePrevious );
			
			// ensure this child belongs to the conductor .
			current = this.EnsureChild ( current );

			if ( this.IsEnabled )
				UIControlExtension.TryEnableChild ( current);

			// set current selection .
			this.m_SelectedChild = current;

			this.RaisePropertyChanged ( "EnabledChild" );
			this.OnChildRequireEnabled ( this.m_SelectedChild, true );
		}

		/// <summary>
		///		Ensures that an item is ready to be enabled .
		/// </summary>
		/// <param name="newChild"></param>
		/// <returns>The item to be activated.</returns>
		protected override T EnsureChild ( T newChild )
		{
			if (newChild == null)
			{
				newChild = GetNextChildToEnabled( this._children,
							this.SelectedChild != null ? this._children.IndexOf(this.SelectedChild) : 0);
			}
			else
			{
				var index = this._children.IndexOf(newChild);

				if (index == -1)
					this._children.Add( newChild);
				else newChild = this._children[index];
			}

			var c = newChild as IUIChild ;
			if ( c != null && c.Parent != this )
				c.Parent = this;

			return newChild;
		}


		protected override void CloseChildImpl ( T child )
		{
			if ( child.Equals( this.SelectedChild) )
			{
				var index = this._children.IndexOf(child);
				var next = GetNextChildToEnabled(_children, index);

				this.ChangeSelectedChild ( next, true );
			}
			else
			{
				UIControlExtension.TryDisableChild (child, true);
			}

			this._children.Remove(child);
		}

		/// <summary>
        ///		Determines the next item to enabled based on the last selection index.
        /// </summary>
		protected virtual T GetNextChildToEnabled ( IList<T> list, int lastIndex)
		{
		    var at = lastIndex - 1;

		    if ( at == -1 && list.Count > 1)
			{
		        return list[1];
		    }

		    if ( at > -1 && at < list.Count - 1)
			{
		        return list[at];
		    }

			// nothing .
		    return default(T);
		}


		/// <summary>
		/// Called to check whether or not this instance can close.
		/// </summary>
		/// <param name="callback">The implementor calls this action with the result of the close check.</param>
		public override void CanClose ( Action<bool> callback)
		{
			this.ClosePolicy.Apply ( this._children, (canClose, closable) =>
			{
				if ( !canClose && closable.Any() )
				{
					if (closable.Contains( this.SelectedChild) )
					{
						var list = this._children.ToList();
						var next = this.SelectedChild;
						do
						{
							var previous = next;
							next = this.GetNextChildToEnabled( list, list.IndexOf(previous) );
							list.Remove(previous);

						} while ( closable.Contains(next) );

						var previousActive = this.SelectedChild;
						this.ChangeSelectedChild(next, true);
						this._children.Remove ( previousActive);

						var stillToClose = closable.ToList();
						stillToClose.Remove(previousActive);
						closable = stillToClose;
					}

					closable.OfType<IUIStatus>().Apply( x => x.SetDisabled(true) );
					this._children.RemoveRange ( closable);
				}

				callback( canClose);
			});
		}

		/// <summary>
		/// Called when activating.
		/// </summary>
		protected override void OnEnabled ()
		{
			UIControlExtension.TryEnableChild ( SelectedChild);
		}

		/// <summary>
		/// Called when deactivating.
		/// </summary>
		/// <param name="close">Inidicates whether this instance will be closed.</param>
		protected override void OnDisabled (bool close)
		{
			if ( close )
			{
				_children.OfType<IUIStatus>().Apply(x => x.SetDisabled(true));
				_children.Clear();
			}
			else
			{
				UIControlExtension.TryDisableChild ( SelectedChild, false );
			}
		}

	}
}